
<!--
 * @Author: your name
 * @Date: 2020-09-15 19:24:00
 * @LastEditTime: 2020-12-10 17:04:17
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \inventory-apie:\hjimi\人脸\html\face-recognition\src\views\Layout\components\Headnav.vue
-->
<style lang="less" scoped>
.cbir_box {
    background: #f4f9ff;
  text-align: center;
  height: 100vh;
}
 .cbir {
  padding-top:40px;
  display: flex;
  justify-content:center;
  .librayListes {
    margin-right: 10px;
    /deep/.el-loading-mask {
      background: transparent!important;
    }
.list {
    width: 216px;
    text-align: left;
    height: 270px;
      overflow: hidden;
      overflow-y: auto;
       &::-webkit-scrollbar {
      width: 3px;
     }
        ::-webkit-scrollbar-corner {
       border-radius: 10px;
     }
        &::-webkit-scrollbar-thumb {
       background: #87c3ff;
       border-radius: 10px;
     }
     &::-webkit-scrollbar-track { 
       background: #efefef;    
       border-radius: 10px;
}
 .create_liabray_tip {
   color: #409EFF;
   .el-button {
     margin-top:6px;  
   }
    span {
      color: #E6A23C;
    }
   .el-icon-warning-outline {
     font-size: 14px;
     font-weight: bold;
      color: #E6A23C;
   }
 }
}
    .score {
      margin-top:20px;
      /deep/.el-input-number {
        margin-left: -15px;
      }
      /deep/.el-switch {
        position: relative;
        top:-2px;
      }
    }
  }
.left {
     width: 400px;
  .left_box {
      border: 1px #409eff dashed;
    height: 484px;
    background: #fafafa;
  }
   .sc {
    margin-top: 22px;
    button {
      width: 200px;
      font-size: 16px;
    }
  }
  .img {position: absolute;left:0;top:0;transform: scale(0.96);}
  .photo {
   width:398px;
    height: 399px;
    overflow: hidden;
    // background: url("../../assets/img/002.png") top center no-repeat;
    background-size: contain;
    position: relative;
  }
}
.left{
  margin-right: 11px;
}
.right {
ul {
    width: 628px;
  height: 720px;
  overflow: hidden;
  overflow-y: auto;
}
ul::-webkit-scrollbar {
  width: 5px;
}
ul::-webkit-scrollbar-corner {
  border-radius: 10px;
}
ul::-webkit-scrollbar-thumb {
  background: #87c3ff;
  border-radius: 10px;
}
ul::-webkit-scrollbar-track { 
            background: #efefef;     
            border-radius: 10px;
}

  .list {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    li {
      width: 200px;
      height: 230px;
      overflow: hidden;
      border:1px #eee solid; margin-bottom: 8px;
    }
    .photoes {
      width: 200px;
      height: 200px;
      overflow: hidden;
      position: relative;
      background: #fff;
      i {
        display: block;
        background: url('../../assets/img/xie.png') top center no-repeat;
        width: 48px;
        height: 48px;
        position: absolute;
        left:-7px;
        top:-7px;
        text-align: center; 
      em {
        color: #fff;
        font-size: 16px;
        position: relative;
        top: 11px;
        right: 6px;
      }
      }
      img {
        transform: scale(.8);
      }
    }

  }
  .percent {
    position: relative;
    span {
      width: 200px;
      height: 30px;
      font-size: 16px;
      color: #134774;
      display: block;
      line-height: 30px;
      position: absolute;
      left: 0;
    };
    .num {
      width: 100%;
      background: #afd6ff;
      z-index: 9;
    }
     .num + .bg {
        background: #edf5ff;
     }
     .bg + span {
       z-index: 10;
     }
  }
  .errTxtTip {
    color: rgb(245, 108, 108);
    font-size: 14px;
    text-align: center;
    line-height: 30px;
  }
}

}
  .p {
  text-align: left;
  color: #999;
  padding-bottom: 10px;
  font-size: 14px;
  }
.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}
.el-icon-plus {
position: absolute;
    top: 50%;
    font-size: 60px;
    margin-left: -25px;
    color: #d7dae2;
}
.compare-scan {
   position: absolute;
    z-index: 7;
    top: 0;
    left: 0;
    width: 500px;
    filter: progid:DXImageTransform.Microsoft.Gradient(startColorStr="transparent",endColorStr="#3e88f1",gradientType="0");
    border-bottom: 3px solid #3e88f1;
    -webkit-animation: scan 1.5s infinite;
    -moz-animation: scan 1.5s infinite;
    animation: scan 1.5s infinite;
    background: -webkit-gradient(linear,left top,left bottom,from(transparent),to(#3e88f1));
    background: -webkit-linear-gradient(top,transparent,#3e88f1);
    background: -moz-linear-gradient(top,transparent,#3e88f1);
    background: linear-gradient(180deg,transparent,#3e88f1);
}
 .tip {
  padding-top: 20px;
  text-align: left;
 p{
    color: #999;
    line-height: 16px;
 }
}
/deep/.el-radio {
  margin-bottom: 15px;
  margin-left: 0!important;
  width:100px;
  margin-right: 0!important;
  overflow: hidden;
}
/deep/.el-loading-spinner i {
    font-size: 22px;
}
.showTip {
  width:100%;height:100%;display:inline-block
}
/deep/.el-radio-group{
  width: 210px;
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
}
.el-icon-info {
    font-size: 14px;
    vertical-align: middle;
    display: inline-block;
    margin-left: 4px;
    cursor: pointer;
    color:#999;
}
.is_disabled {
  cursor: not-allowed;
}
</style>
<template>
<div class="cbir_box">
<div class="cbir">
      <div class="librayListes">
           <p class="p">脸库编码列表：</p>
          <div class="list" v-loading="getLibraryCode_loading">
            <div class="create_liabray_tip" v-show="create_liabray_tip"><i class="el-icon-warning-outline"></i> <span>请先创建脸库并导入图片，再检索！</span>
            <el-button type="primary" size="small" @click="$router.push({path:'/faceManagement',name: 'faceManagement', params: {createShow: true}})">去创建脸库 <i class="el-icon-right"></i></el-button>
            </div>
            <el-radio-group v-model="radio1" size="mini" @change="getsLibraryCode">
              <el-radio v-for="(libraryList, index) of libraryListes" :key="index" :label="index" border>
                <el-tooltip :content="libraryList.libraryCode" :placement="(index + 1) % 2 == 0 ? 'right' : 'left' " effect="light">
                <span class="showTip">{{ libraryList.libraryCode }}</span></el-tooltip></el-radio>
            </el-radio-group>
        </div>
        <div class="score">
            <p class="p">检索结果最低分数（0.01 ~ 1）：</p>
           <el-input-number size="medium" :disabled="create_liabray_tip" v-model="imgParams.score" controls-position="right" step-strictly :step="0.01" @change="handleChangeScore" :min="0.01" :max="1"></el-input-number>
        </div>
         <div class="score">
            <p class="p">检索结果数目（1 ~ 500）：</p>
           <el-input-number size="medium" :disabled="create_liabray_tip" v-model="imgParams.topNum" step-strictly :step="1" :min="1" :max="500"></el-input-number>
        </div>
         <div class="score" style="text-align:left">
         <span class="p">图片质量评估：</span><el-switch v-model="imgParams.isQuality" :disabled="create_liabray_tip" @change="zhiliang"></el-switch>
         <el-popover
             placement="top-start"
             title="图片质量评估项："
             width="20"
             trigger="hover"
             :content='qualityTip'>
             <i slot="reference" class="el-icon-info"></i>
       </el-popover>
        </div>
      </div>
       <div class="left">
       <p class="p">被查人脸（图片中主体部分）：</p>
       <div class="left_box">
         <form id="pos" >
           <el-upload
          class="avatar-uploader"
          action="apis/algo/library/search/image"
          :data="imgParams"
          :on-error="imgError"
          :show-file-list="false"
          :on-success="handleAvatarSuccess"
          :before-upload="beforeAvatarUpload" 
          :auto-upload="true"
          :http-request="httpRequest" 
          :disabled="create_liabray_tip"
         >
         <div>
            <div class="photo">
           <div class="compare-scan" v-if="db_animate"></div>
            <i class="el-icon-plus"></i>
           <img class="img" v-if="imageUrl" :src="imageUrl" width="100%">
           </div>
          <div class="sc">
            <el-button type="primary" :disabled="create_liabray_tip">本地上传<i class="el-icon-upload el-icon--right"></i></el-button>
          </div>
         </div>
        </el-upload>
      </form>
       </div>
      <div class="tip"><p>图片文件支持PNG、JPG、JPEG、BMP，图片大小不超过3M，人脸对比只可对比图片中主体部分。</p></div>
     </div>
     <div class="right">
     <p class="p">检索结果（按相似度降序排列）：</p>
     <ul class="list" v-loading="loading" element-loading-text="拼命查找中..."  element-loading-spinner="el-icon-loading">
       <p v-if="errTxtTip" class="errTxtTip">{{ errTxt }}</p>
       <li v-for="(scorePhoto, index) of scorePhotes" :key="index">
         <div class="photoes">
           <i><em>{{ index + 1 }}</em></i>
           <img :src="scorePhoto.url" width="100%">
         </div>
         <div class="percent">
           <span class="num" :style="{width: scorePhoto.score >= 1 ? '100%' : scoreHandle(scorePhoto.score) + '%' }"></span>
           <span class="bg"></span>
           <span>{{
              scorePhoto.score != 1 ? scorePhoto.score < 1 ? `相似度为 ${ scoreHandle(scorePhoto.score) }%` : '可能为本人' : '可能为本人' }}</span>
         </div>
       </li>
     </ul>
     </div>
 </div>
  </div>
</template>
<script>
import { 
  imageSearch //人脸上传搜索
  } from "@/api/cbir"
import { 
  queryLibrary, //脸库列表
  getFaceImage, //获取单张人脸
   } from "@/api/faceManagement"
import { qualityTip } from '@/utils/textTip'
import { arrObjectUpDownSort } from '@/utils/arrHandle'
export default {
  name: "cbir",
  data() {
    return {
      qualityTip: qualityTip() + '检测',
      loading: false,
      errTxtTip: false,
      errTxt: '',
      errTxt_1: '查找失败，请重新上传',
      errTxt_2: '无匹配目标，请另选上传',
      getLibraryCode_loading: false,
      radio1: 0,
      scorePhotes: [
        {
            url: require('../../assets/img/002.png'),
            score: 0.55
        },
        {
            url: require('../../assets/img/002.png'),
            score: 0.87
        },
        {
            url: require('../../assets/img/002.png'),
            score: 0.92
        },
        {
            url: require('../../assets/img/002.png'),
            score: 0.92
        },
         {
            url: require('../../assets/img/002.png'),
            score: 1
        },
        {
            url: require('../../assets/img/002.png'),
            score: 0.92
        },
        {
            url: require('../../assets/img/002.png'),
            score: 0.92
        },
        {
            url: require('../../assets/img/002.png'),
            score: 0.92
        },
         {
            url: require('../../assets/img/002.png'),
            score: 0.92
        },
        {
            url: require('../../assets/img/002.png'),
            score: 0.92
        },
         {
            url: require('../../assets/img/002.png'),
            score: 1
        },
         {
            url: require('../../assets/img/002.png'),
            score: 1
        },
         {
            url: require('../../assets/img/002.png'),
            score: 1
        },
         {
            url: require('../../assets/img/002.png'),
            score: 1
        },
         {
            url: require('../../assets/img/002.png'),
            score: 0.8
        }
      ],
      imgParams: {
        score: 0.01,
        topNum: 50,
        isQuality: true,
        libraryCode: '',
        // 'imageDesc.format': '',
        // 'imageDesc.width': '',
        // 'imageDesc.height': '',
        //  file: '',
         width: '',
         height: ''
      },
      libraryListes: [],
      imageUrl: require('../.././assets/img/002.png'),
      db_animate: false,
      errorMark: true, //上传失败标识
      
    };
  },
  computed: {
     create_liabray_tip() {
     return this.libraryListes.length === 0 ? true : false
    }
  },
  methods: {
    getsLibraryCode() {
        this.imgParams.libraryCode = this.libraryListes[this.radio1].libraryCode
    },
    handleAvatarSuccess(res, file) {
      this.loading = true
      this.fileUrl(res, file.raw,'db_animate','imageUrl')
    },
    scoreHandle(x) {
      // score 算法为：>=1为100%  <=0为0%   返回的小数为3-8个
      let score = x.toString(),
          scoreResult = score.substr(score.indexOf('.') + 1, 2) //截取小数
       if(scoreResult.length === 2 && scoreResult[0] == 0) {  //处理score为2个小数的值 如：0.88
           return `${ scoreResult[0] }.${ scoreResult[1] }`
        } else if(score.length === 3 && score > 0 && score < 1) {  //处理score为1个小数的值 如：0.8
          return `${ scoreResult[0] }0`
        } else if(score >= 1) {
          return 100
        } else {
          return scoreResult
        }
      if(score <= 0) {
        return 0
      }
    },
// 上传前校验
    beforeAvatarUpload(file) {
       this.loading = true
      //  this.scorePhotes = []
      this.imgRule(file.type, file.size, file)
    },
//上传成功
    fileUrl (res, fileRaw, animate, imageUrl) {
       let _this = this
       this[imageUrl] = URL.createObjectURL(fileRaw);
       this[animate] = this[imageUrl] ? true : false //展示搜索动画
    },
    imgRule (fileType, fileSize, fileRaw) {
      let params = this.imgParams,
          readers = new FileReader()
     function imageType () { return fileType === 'image/jpeg' || fileType === 'image/jpg' || fileType === 'image/png' || fileType === 'image/bmp' || !fileType }
     const isLt1M = fileSize / 1024 / 1024 < 3;
        if (!imageType()) { 
          this.$message.error('上传人脸图片只能是四种格式（jpg/jpeg/png/bmp）!')
          this.txtTip()
          } else if (imageType() && !isLt1M) {
             this.$message.error('上传人脸图片大小不能超过3MB!')
             this.txtTip()
          } else if (!imageType() && !isLt1M) {
             this.$message.error('上传人脸图片大小不能超过3MB,只能是四种格式（jpg/jpeg/png/bmp）!')
             this.txtTip()
          } else {
                  let format = fileType.substr(fileType.indexOf('/') + 1)
                   params['format'] = format.toUpperCase()
                   if(params['format'] === 'JPEG') {
                     params['format'] = 'JPG'
                   }
                         new Promise((reslove) => {
                           readers ? reslove() : String
                         }).then(() => {
                            readers.readAsDataURL(fileRaw)
                            readers.onload = function (e) {
                            let url = e.target.result,
                                img = new Image()
                                img.src = url
                            img.onload = function () { 
                                params.width = img.width
                                params.height = img.height
                            }
                        }
                         })
          }
        return imageType() && isLt1M;  
    },
     async httpRequest(content){
         let imgParams = this.imgParams,
             formData = new FormData(document.getElementById('pos')) 
          formData.delete('file') //必须先删除虚拟form文件信息
            let param = {
                "libraryCode": imgParams['libraryCode'],
                "topNum":imgParams['topNum'],
                "minScore": imgParams['score'], //若不传score默认为0.5
                "isQuality": imgParams['isQuality'],
                "imageDesc": {
                "format": imgParams['format']
            }
          }
          formData.append("param", new Blob([JSON.stringify(param)], { type:"application/json" }))
          formData.append('file', content.file) 
           setTimeout(() => {
              // formData.append('imageDesc.width', imgParams['width'])
              // formData.append('imageDesc.height', imgParams['height'])
              imageSearch(formData).then((res) => {
                if(res.code === 0) {
                      if(res.data !== null && res.data !== undefined && res.data.length > 0) {
                        this.loading = this.errTxtTip = false
                        this.scorePhotes = []
                         setTimeout(() => {
                            this.db_animate = this['loading'] = false
                         }, 1000);
                          this.$message.success(content.file.name + '上传成功')
                           res.data.map((item) => { //遍历得到的图片id和相似值
                             getFaceImage( //根据脸库编码和图片id获取图片
                               {
                                 libraryCode: imgParams['libraryCode'],
                                 imageId: item.imageId
                               }
                             ).then((res1) => {
                               if(res1.code === 0 && res1.data) {
                                   this.scorePhotes.push(
                                   {
                                     url: 'data:image/jpeg;base64,' + res1.data,
                                     score: item.score
                                   }
                                 )
                                arrObjectUpDownSort(this.scorePhotes,'score', 'down') //对检索结果的对象数组降序排列
                               }
                             })
                           })
                      } else {
                         this.$message.warning(this.errTxt_2, 5000)
                         setTimeout(() => {
                           this.scorePhotes = []
                            this.db_animate = this['loading'] = false
                            this.errTxtTip = true
                            this.errTxt = this.errTxt_2
                         }, 1600);
                      }
                     } else {
                        this.db_animate = this['loading'] = false
                        this.imageUrl = ''
                        this.scorePhotes = []
                        this.errTxtTip = true
                        this.errTxt = this.errTxt_1
              }
                })
           }, 22)
            },
// 脸库列表
    getLibrarys() {
      this.getLibraryCode_loading = true
      queryLibrary().then((res) => {
         if(res.code === 0 && typeof res.data === 'object' && res.data.length !== 0) {
           this.getLibraryCode_loading = false
          let data = res.data
            data.map((item) => {
           this.libraryListes.push(
            {
              id: item.id,
              libraryCode: item.code,
            }
          )
        })
        this.imgParams.libraryCode = this.libraryListes[0].libraryCode
         } else {
          this.getLibraryCode_loading = false
         }
      })
    },
// 控制输入返回score值
    handleChangeScore() {
    if(this.imgParams.score === 1.0) {
      this.imgParams.score = 1
    }
    },
     zhiliang() {
      this.$message.success(this.imgParams.isQuality ? '已开启图片质量评估，请上传图片检索！' : '已关闭图片质量评估，请上传图片检索！')
    },
    txtTip () {
      let _this = this
       _this.errTxtTip = true
       _this.loading = false
        _this.imageUrl = ''
        _this.scorePhotes = []
        _this.errorMark = false
    },
// 上传失败
    imgError(err, file, fileList) {
    // let _this = this
    //  this.errorMark == true ? errTip() : String
    //  function errTip () {          
    //     _this.$message({
    //            message: err.type == 'error' ? file.name + ' 上传失败，请重试' : '上传失败，请重试',
    //             type: "error",
    //             durantion: 3 * 1000
    //        })
    //     _this.loading = false
    //  }
   },
  },
 created() {
   this.getLibrarys()
    // console.log(arrObjectUpDownSort(this.scorePhotes, 'score', 'down'))
 }
};
</script>

